﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SJHT_CustomerVoiceDownLoad.Common
{
    public class EncryptAndDecode
    {
        /// <summary>
        ///　对appSettings节点添加健值
        ///　如果健已经存在则更改值
        ///　添加后重新保存并刷新该节点
        /// </summary>
        /// <param name="dict">添加的健值集合</param>
        /// <param name="isProtected">是否加密appSettings节点数据,如果为TrueappSettings节点下所有数据都会被加密</param>
        public static void AddConfig(System.Collections.Generic.Dictionary<string, string> dict, bool isProtected)
        {
            if (dict == null || dict.Count <= 0) return;
            System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            //循环添加或更改健值
            foreach (System.Collections.Generic.KeyValuePair<string, string> key_value in dict)
            {
                if (string.IsNullOrEmpty(key_value.Key)) continue;
                if (configuration.AppSettings.Settings[key_value.Key] != null)
                    configuration.AppSettings.Settings[key_value.Key].Value = key_value.Value;
                else
                    configuration.AppSettings.Settings.Add(key_value.Key, key_value.Value);
            }

            //保存配置文件
            try
            {
                //加密配置信息
                if (isProtected && !configuration.AppSettings.SectionInformation.IsProtected)
                {
                    configuration.AppSettings.SectionInformation.ForceSave = true;
                    configuration.AppSettings.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                }
                configuration.Save();
            }
            catch (Exception)
            {
                throw;
            }
            ConfigurationManager.RefreshSection("appSettings");
        }

        ///<summary>
        ///读取connectionStrings配置节 依据连接串名字connectionName返回数据连接字符串
        ///</summary>
        ///<param name="connectionName"></param>
        ///<returns></returns>
        private static string GetConnectionStringsConfig(string connectionName)
        {
            string connectionString =
                    ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString();
            Console.WriteLine(connectionString);
            return connectionString;
        }

        ///<summary>
        ///更新connectionStrings配置节 更新连接字符串
        ///</summary>
        ///<param name="newName">连接字符串名称</param>
        ///<param name="newConString">连接字符串内容</param>
        ///<param name="newProviderName">数据提供程序名称</param>
        private static void UpdateConnectionStringsConfig(string newName,string newConString,string newProviderName)
        {
            bool isModified = false;    //记录该连接串是否已经存在
                                        //如果要更改的连接串已经存在
            if (ConfigurationManager.ConnectionStrings[newName] != null)
            {
                isModified = true;
            }
            //新建一个连接字符串实例
            ConnectionStringSettings mySettings =
                new ConnectionStringSettings(newName, newConString, newProviderName);
            // 打开可执行的配置文件*.exe.config
            Configuration config =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            // 如果连接串已存在，首先删除它
            if (isModified)
            {
                config.ConnectionStrings.ConnectionStrings.Remove(newName);
            }
            // 将新的连接串添加到配置文件中.
            config.ConnectionStrings.ConnectionStrings.Add(mySettings);
            // 保存对配置文件所作的更改
            config.Save(ConfigurationSaveMode.Modified);
            // 强制重新载入配置文件的ConnectionStrings配置节
            ConfigurationManager.RefreshSection("ConnectionStrings");
        } 

        ///<summary>
        ///读取appStrings配置节 返回＊.exe.config文件中appSettings配置节的value项
        ///</summary>
        ///<param name="strKey"></param>
        ///<returns></returns>
        private static string GetAppConfig(string strKey)
        {
            foreach (string key in ConfigurationManager.AppSettings)
            {
                if (key == strKey)
                {
                    return ConfigurationManager.AppSettings[strKey];
                }
            }
            return null;
        }

        ///<summary>
        ///更新connectionStrings配置节 在＊.exe.config文件中appSettings配置节增加一对键、值对
        ///</summary>
        ///<param name="newKey"></param>
        ///<param name="newValue"></param>
        private static void UpdateAppConfig(string newKey, string newValue)
        {
            bool isModified = false;
            foreach (string key in ConfigurationManager.AppSettings)
            {
                if (key == newKey)
                {
                    isModified = true;
                }
            }

            // Open App.Config of executable
            Configuration config =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            // You need to remove the old settings object before you can replace it
            if (isModified)
            {
                config.AppSettings.Settings.Remove(newKey);
            }
            // Add an Application Setting.
            config.AppSettings.Settings.Add(newKey, newValue);
            // Save the changes in App.config file.
            config.Save(ConfigurationSaveMode.Modified);
            // Force a reload of a changed section.
            ConfigurationManager.RefreshSection("appSettings");
        }

        /*
        请注意：(1)要使用以下的代码访问app.config文件，除添加引用System.Configuration外，还必须在项目添加对System.Configuration.dll的引用; 
        (2)以下示例代码中的DPAPI提供程序为“DataProtectionConfigurationProvider”，这是一种基于机器名和当前用户密码的加密方式。
        如果计划在多台服务器（Web 场合）上使用相同的加密配置文件，则只有通过 RSAProtectedConfigurationProvider 才能导出加密密钥，并将其导入其他服务器。
        (3)加密后的配置文件不需要解密即可用上述方法直接读取。
        加密connectionStrings配置节
        */
        ///<summary>
        ///加密配置文件中的ConnectionString节
        ///</summary>
        ///<param name="protect">true为加密，false为解密</param>
        public static void ConnectionStringProtection(bool protect)
        {
            //取得当前程序的执行路径
            string pathName = Application.ExecutablePath;
            // 定义Dpapi提供程序的名称.
            string strProvider = "DataProtectionConfigurationProvider";

            System.Configuration.Configuration oConfiguration = null;
            System.Configuration.ConnectionStringsSection oSection = null;

            try
            {
                // 打开配置文件，并取得connectionStrings配置节.
                oConfiguration =
                        System.Configuration.ConfigurationManager.OpenExeConfiguration(pathName);

                if (oConfiguration != null)
                {
                    bool blnChanged = false;
                    oSection = oConfiguration.GetSection("connectionStrings") as
                        System.Configuration.ConnectionStringsSection;

                    if (oSection != null)
                    {
                        if ((!(oSection.ElementInformation.IsLocked)) && (!(oSection.SectionInformation.IsLocked)))
                        {
                            if (protect)
                            {
                                if (!(oSection.SectionInformation.IsProtected))
                                {
                                    blnChanged = true;
                                    // 加密connectionStrings配置节.
                                    oSection.SectionInformation.ProtectSection(strProvider);
                                }
                            }
                            else
                            {
                                if (oSection.SectionInformation.IsProtected)
                                {
                                    blnChanged = true;
                                    // 解密connectionStrings配置节.
                                    oSection.SectionInformation.UnprotectSection();
                                }
                            }
                        }

                        if (blnChanged)
                        {
                            // 如果connectionStrings配置节被更改，则强制保存它.
                            oSection.SectionInformation.ForceSave = true;
                            // 保存对connectionStrings配置节的更改.
                            oConfiguration.Save();
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                throw (ex);
            }
            finally
            {
            }
        }

        ///<summary>
        ///加密配置文件中的AppSettings配置节
        ///</summary>
        ///<param name="protect">true为加密，false为解密</param>
        public static void AppSettingProtection(bool protect)
        {
            //取得当前程序的执行路径
            string pathName = Application.ExecutablePath;
            // Define the Dpapi provider name.
            string strProvider = "DataProtectionConfigurationProvider";

            System.Configuration.Configuration oConfiguration = null;
            System.Configuration.AppSettingsSection oSection = null;

            try
            {
                // Open the configuration file and retrieve the connectionStrings section.
                oConfiguration =
                    System.Configuration.ConfigurationManager.OpenExeConfiguration(pathName);

                if (oConfiguration != null)
                {
                    bool blnChanged = false;
                    oSection = oConfiguration.GetSection("appSettings") as
                        System.Configuration.AppSettingsSection;

                    if (oSection != null)
                    {
                        if ((!(oSection.ElementInformation.IsLocked)) &&
                                (!(oSection.SectionInformation.IsLocked)))
                        {
                            if (protect)
                            {
                                if (!(oSection.SectionInformation.IsProtected))
                                {
                                    blnChanged = true;
                                    // Encrypt the section.
                                    oSection.SectionInformation.ProtectSection(strProvider);
                                }
                            }
                            else
                            {
                                if (oSection.SectionInformation.IsProtected)
                                {
                                    blnChanged = true;
                                    // Remove encryption.
                                    oSection.SectionInformation.UnprotectSection();
                                }
                            }
                        }

                        if (blnChanged)
                        {
                            // Indicates whether the associated configuration section will be saved even   
                            // if it has not been modified.
                            oSection.SectionInformation.ForceSave = true;
                            // Save the current configuration.
                            oConfiguration.Save();
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                throw (ex);
            }
            finally
            {
            }
        }
    }
}
